using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;

namespace KeyAuthDemo
{
    public static class KeyAuth
    {
        // 错误码
        public const int SUCCESS = 0;
        public const int ERROR_GENERAL = 1;
        
        // 算法类型
        public const string ALGO_SM2 = "SM2";
        public const string ALGO_ECDSA_P256 = "ECDSA_P256";
        
        // 导入函数
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int KeyAuthGenerateKeyPair(
            [MarshalAs(UnmanagedType.LPStr)] string algo,
            out IntPtr pubKey,
            out IntPtr priKey);
        
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int KeyAuthSign(
            [MarshalAs(UnmanagedType.LPStr)] string algo,
            [MarshalAs(UnmanagedType.LPStr)] string priKey,
            byte[] data,
            int dataLen,
            out IntPtr signature,
            out int signatureLen);
            
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int KeyAuthVerify(
            [MarshalAs(UnmanagedType.LPStr)] string algo,
            [MarshalAs(UnmanagedType.LPStr)] string pubKey,
            byte[] data,
            int dataLen,
            byte[] signature,
            int signatureLen);
        
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int KeyAuthSignJSON(
            [MarshalAs(UnmanagedType.LPStr)] string algo,
            [MarshalAs(UnmanagedType.LPStr)] string priKey,
            [MarshalAs(UnmanagedType.LPStr)] string jsonData,
            out IntPtr signature,
            out int signatureLen);
        
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int KeyAuthVerifyJSON(
            [MarshalAs(UnmanagedType.LPStr)] string algo,
            [MarshalAs(UnmanagedType.LPStr)] string pubKey,
            [MarshalAs(UnmanagedType.LPStr)] string jsonData,
            byte[] signature,
            int signatureLen);
        
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int KeyAuthQuery(
            [MarshalAs(UnmanagedType.LPStr)] string chainID,
            [MarshalAs(UnmanagedType.LPStr)] string nodeAddr,
            int nodePort,
            [MarshalAs(UnmanagedType.LPStr)] string contractName,
            [MarshalAs(UnmanagedType.LPStr)] string method,
            [MarshalAs(UnmanagedType.LPStr)] string privateKey,
            [MarshalAs(UnmanagedType.LPStr)] string paramsJSON,
            out IntPtr result);
            
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int KeyAuthInvoke(
            [MarshalAs(UnmanagedType.LPStr)] string chainID,
            [MarshalAs(UnmanagedType.LPStr)] string nodeAddr,
            int nodePort,
            [MarshalAs(UnmanagedType.LPStr)] string contractName,
            [MarshalAs(UnmanagedType.LPStr)] string method,
            [MarshalAs(UnmanagedType.LPStr)] string privateKey,
            [MarshalAs(UnmanagedType.LPStr)] string paramsJSON,
            out IntPtr result);
            
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void KeyAuthFree(IntPtr ptr);
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("KeyAuth Core 综合示例 (C#)");
            Console.WriteLine("========================");
            
            // 1. 生成密钥对
            Console.WriteLine("\n[1] 生成密钥对");
            IntPtr pubKeyPtr, priKeyPtr;
            if (KeyAuth.KeyAuthGenerateKeyPair(KeyAuth.ALGO_SM2, out pubKeyPtr, out priKeyPtr) == KeyAuth.SUCCESS)
            {
                string pubKey = Marshal.PtrToStringAnsi(pubKeyPtr);
                string priKey = Marshal.PtrToStringAnsi(priKeyPtr);
                
                Console.WriteLine($"公钥: {pubKey}");
                Console.WriteLine($"私钥: {priKey}");
                
                // 2. 签名与验证
                Console.WriteLine("\n[2] 签名与验证");
                byte[] data = Encoding.UTF8.GetBytes("Hello, World!");
                IntPtr signaturePtr;
                int signatureLen;
                
                if (KeyAuth.KeyAuthSign(KeyAuth.ALGO_SM2, priKey, data, data.Length, out signaturePtr, out signatureLen) == KeyAuth.SUCCESS)
                {
                    Console.WriteLine($"签名成功，长度: {signatureLen} 字节");
                    
                    // 复制签名数据
                    byte[] signature = new byte[signatureLen];
                    Marshal.Copy(signaturePtr, signature, 0, signatureLen);
                    
                    if (KeyAuth.KeyAuthVerify(KeyAuth.ALGO_SM2, pubKey, data, data.Length, signature, signature.Length) == KeyAuth.SUCCESS)
                    {
                        Console.WriteLine("签名验证成功");
                    }
                    else
                    {
                        Console.WriteLine("签名验证失败");
                    }
                    
                    KeyAuth.KeyAuthFree(signaturePtr);
                }
                
                // 2.1 JSON签名与验证
                Console.WriteLine("\n[2.1] JSON签名与验证");
                string jsonData = "{\"name\": \"KeyAuth\", \"version\": \"1.0\", \"features\": [\"签名\", \"验证\", \"安全存储\"]}";
                IntPtr jsonSignaturePtr;
                int jsonSignatureLen;
                if (KeyAuth.KeyAuthSignJSON(KeyAuth.ALGO_SM2, priKey, jsonData, out jsonSignaturePtr, out jsonSignatureLen) == KeyAuth.SUCCESS)
                {
                    Console.WriteLine($"JSON签名成功，长度: {jsonSignatureLen} 字节");
                    byte[] jsonSignature = new byte[jsonSignatureLen];
                    Marshal.Copy(jsonSignaturePtr, jsonSignature, 0, jsonSignatureLen);
                    if (KeyAuth.KeyAuthVerifyJSON(KeyAuth.ALGO_SM2, pubKey, jsonData, jsonSignature, jsonSignature.Length) == KeyAuth.SUCCESS)
                    {
                        Console.WriteLine("JSON签名验证成功");
                    }
                    else
                    {
                        Console.WriteLine("JSON签名验证失败");
                    }
                    KeyAuth.KeyAuthFree(jsonSignaturePtr);
                }
                else
                {
                    Console.WriteLine("JSON签名失败");
                }
                
                // 3. 合约查询
                Console.WriteLine("\n[3] 合约查询");
                string chainID = "chain1";
                string nodeAddr = "127.0.0.1";
                int nodePort = 12301;
                string contractName = "contract_name";
                string queryMethod = "query_method";
                string paramsJSON = "{\"key\":\"value\"}";
                
                IntPtr queryResultPtr;
                if (KeyAuth.KeyAuthQuery(
                    chainID, nodeAddr, nodePort, 
                    contractName, queryMethod, 
                    priKey, paramsJSON, out queryResultPtr) == KeyAuth.SUCCESS)
                {
                    string queryResultJSON = Marshal.PtrToStringAnsi(queryResultPtr);
                    Console.WriteLine("查询合约成功:");
                    PrintContractResult(queryResultJSON);
                    KeyAuth.KeyAuthFree(queryResultPtr);
                }
                
                // 4. 合约调用
                Console.WriteLine("\n[4] 合约调用");
                string invokeMethod = "invoke_method";
                IntPtr invokeResultPtr;
                
                if (KeyAuth.KeyAuthInvoke(
                    chainID, nodeAddr, nodePort, 
                    contractName, invokeMethod, 
                    priKey, paramsJSON, out invokeResultPtr) == KeyAuth.SUCCESS)
                {
                    string invokeResultJSON = Marshal.PtrToStringAnsi(invokeResultPtr);
                    Console.WriteLine("调用合约成功:");
                    PrintContractResult(invokeResultJSON);
                    KeyAuth.KeyAuthFree(invokeResultPtr);
                }
                
                // 释放内存
                KeyAuth.KeyAuthFree(pubKeyPtr);
                KeyAuth.KeyAuthFree(priKeyPtr);
            }
            else
            {
                Console.WriteLine("生成密钥对失败");
            }
            
            Console.WriteLine("\n示例完成!");
        }
        
        // 解析并打印合约结果
        static void PrintContractResult(string resultJSON)
        {
            Console.WriteLine($"合约结果JSON: {resultJSON}");
            
            try
            {
                using (JsonDocument doc = JsonDocument.Parse(resultJSON))
                {
                    JsonElement root = doc.RootElement;
                    
                    if (root.TryGetProperty("tx_id", out JsonElement txIdElement))
                    {
                        Console.WriteLine($"交易ID: {txIdElement.GetString()}");
                    }
                    
                    if (root.TryGetProperty("code", out JsonElement codeElement))
                    {
                        Console.WriteLine($"结果代码: {codeElement.GetInt32()}");
                    }
                    
                    if (root.TryGetProperty("message", out JsonElement messageElement))
                    {
                        Console.WriteLine($"消息: {messageElement.GetString()}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"解析JSON失败: {ex.Message}");
            }
        }
    }
} 